package cn.jetpiece.cloud.joss.app.modular.object.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.jetpiece.cloud.joss.app.core.constant.OssConstants;
import cn.jetpiece.cloud.joss.app.modular.object.mapper.RegionMapper;
import cn.jetpiece.cloud.joss.app.modular.object.service.BucketService;
import cn.jetpiece.cloud.joss.app.modular.object.service.RegionService;
import cn.jetpiece.cloud.joss.app.modular.object.wrapper.RegionWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.jetpiece.cloud.joss.api.object.model.params.CreateRegionParam;
import cn.jetpiece.cloud.joss.api.object.model.params.UpdateRegionParam;
import cn.jetpiece.cloud.joss.api.object.model.query.RegionQuery;
import cn.jetpiece.cloud.joss.api.object.model.result.RegionResult;
import cn.jetpiece.cloud.joss.app.modular.object.entity.Bucket;
import cn.jetpiece.cloud.joss.app.modular.object.entity.Region;
import cn.jetpiece.cloud.joss.app.modular.object.enums.BasicExceptionEnum;
import cn.jetpiece.cloud.core.page.PageFactory;
import cn.jetpiece.cloud.model.exception.ServiceException;
import cn.jetpiece.cloud.model.page.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;

/**
 * <p>
 * 域 服务实现类
 * </p>
 *
 * @author XuJZ
 * @since 2020-09-05
 */
@Service
public class RegionServiceImpl extends ServiceImpl<RegionMapper, Region> implements RegionService {
    private RedisTemplate<String, Object> redisTemplate;
    private BucketService bucketService;

    @Autowired
    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Autowired
    public void setBucketService(BucketService bucketService) {
        this.bucketService = bucketService;
    }

    @Override
    public boolean add(CreateRegionParam param) {
        LambdaQueryWrapper<Region> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Region::getEnName, param.getEnName());
        wrapper.eq(Region::getProviderId, param.getProviderId());
        if (super.count(wrapper) > 0) {
            throw new ServiceException(BasicExceptionEnum.REGION_REPEAT);
        }
        Region bean = new Region();
        BeanUtil.copyProperties(param, bean);
        return super.save(bean);
    }

    @Override
    public boolean update(UpdateRegionParam param) {
        Region oldBean = super.getById(param.getId());
        if (oldBean == null) {
            throw new ServiceException(BasicExceptionEnum.REGION_NOT_EXISTED);
        }
        if (StrUtil.isNotEmpty(param.getEnName())) {
            LambdaQueryWrapper<Region> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Region::getEnName, param.getEnName());
            wrapper.eq(Region::getProviderId, param.getProviderId());
            wrapper.ne(Region::getId, oldBean.getId());
            if (super.count(wrapper) > 0) {
                throw new ServiceException(BasicExceptionEnum.REGION_REPEAT);
            }
        }
        Region update = BeanUtil.copyProperties(param, Region.class);
        update.setId(param.getId());
        update.setId(param.getId());
        boolean result = super.updateById(update);
        if (result) {
            redisTemplate.boundHashOps(OssConstants.REGION).delete(update.getId());
        }
        return result;
    }

    @Override
    public Region getById(Serializable id) {
        if (ObjectUtil.isEmpty(id)) {
            return null;
        }
        Region region = (Region) redisTemplate.boundHashOps(OssConstants.REGION).get(id);
        if (region == null) {
            region = super.getById(id);
            if (region == null) {
                return null;
            }
            redisTemplate.boundHashOps(OssConstants.REGION).put(id, region);
        }
        return region;
    }

    @Override
    public boolean delete(String id) {
        Region bean = super.getById(id);
        if (bean == null) {
            throw new ServiceException(BasicExceptionEnum.REGION_NOT_EXISTED);
        }
        LambdaQueryWrapper<Bucket> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Bucket::getRegionId, id);
        if (bucketService.count(wrapper) > 0) {
            throw new ServiceException(BasicExceptionEnum.REGION_CANNOT_DELETE_WITHOUT_NULL);
        }
        boolean result = super.removeById(id);
        if (result) {
            redisTemplate.boundHashOps(OssConstants.REGION).delete(id);
        }
        return result;
    }

    @Override
    public PageResult<RegionResult> page(RegionQuery param) {
        LambdaQueryWrapper<Region> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotEmpty(param.getId())) {
            wrapper.eq(Region::getId, param.getId());
        }
        if (StrUtil.isNotEmpty(param.getProviderId())) {
            wrapper.eq(Region::getProviderId, param.getProviderId());
        }
        if (StrUtil.isNotEmpty(param.getCnName())) {
            wrapper.like(Region::getCnName, param.getCnName());
        }
        if (StrUtil.isNotEmpty(param.getEnName())) {
            wrapper.like(Region::getEnName, param.getEnName());
        }
        if (StrUtil.isNotEmpty(param.getProtocol())) {
            wrapper.eq(Region::getProtocol, param.getProtocol());
        }
        if (StrUtil.isNotEmpty(param.getInternetEndpoint())) {
            wrapper.eq(Region::getInternetEndpoint, param.getInternetEndpoint());
        }
        if (StrUtil.isNotEmpty(param.getInternalEndpoint())) {
            wrapper.eq(Region::getInternalEndpoint, param.getInternalEndpoint());
        }
        if (param.getIsEnable() != null) {
            wrapper.eq(Region::getIsEnable, param.getIsEnable());
        }
        IPage<Region> iPage = PageFactory.defaultPage();
        IPage<Region> page = super.page(iPage, wrapper);
        return new RegionWrapper(page).setWrapper(param.getWrapper()).wrapPageResult();
    }
}
